package cn.itcalvin.sncoal.cth.aspect;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.itcalvin.sncoal.cth.exception.AuthException;
import cn.itcalvin.sncoal.cth.exception.BusinessException;
import cn.itcalvin.sncoal.cth.pojo.common.ReqLong;
import cn.itcalvin.sncoal.cth.pojo.common.RespUserInfo;
import cn.itcalvin.sncoal.cth.service.LogOpService;
import cn.itcalvin.sncoal.cth.utils.JwtUtil;
import cn.itcalvin.vo.Message;
import cn.itcalvin.vo.ResultStatus;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @Classname SncoalAspect
 * @Description 日志记录，以及接口授权判断
 * @Version 1.0.0
 * @Date 2023/2/8 14:29
 * @Created by CALVIN
 */
@Aspect
@Slf4j
@Component
public class CthAspect {
    @Resource
    private HttpServletRequest request;
    @Resource
    private LogOpService logOpService;

    /**
     * 判断接口授权情况
     */
    private RespUserInfo userInfo;

    @Pointcut(value ="within(cn.itcalvin.sncoal.cth.controller..*)")
    private void aspectPointcut() {

    }

    /**
     * 判断接口授权情况
     * @param point
     */
    @Before(value = "aspectPointcut()")
    public void  before(JoinPoint point){
        //如果notAuthAnnotation为空，则需要判断token
        // 获取注解中的参数值
        MethodSignature methodSignature = (MethodSignature)point.getSignature();
        Method method = methodSignature.getMethod();
        // 获取注解Action
        cn.itcalvin.sncoal.cth.aspect.NotAuthAnnotation notAuthAnnotation = method.getAnnotation(cn.itcalvin.sncoal.cth.aspect.NotAuthAnnotation.class);
        if(notAuthAnnotation==null){
            userInfo = JwtUtil.getUserInfo();
            if(userInfo==null){
                throw new AuthException("请登录后进行操作！");
            }
        }
        cn.itcalvin.sncoal.cth.aspect.RoleAnnotation roleAnnotation = method.getAnnotation(cn.itcalvin.sncoal.cth.aspect.RoleAnnotation.class);
        if(roleAnnotation!=null){
            userInfo = JwtUtil.getUserInfo();
            if(userInfo==null){
                throw new AuthException("请登录后进行操作！");
            }
            if(!roleAnnotation.value().contains(userInfo.getRoleType().toString())){
                throw new BusinessException("无该资源权限，请联系系统运维人员！");
            }
        }

    }


    @Around("@annotation(logAnnotation)")
    public Object after(ProceedingJoinPoint point, LogAnnotation logAnnotation){
        MethodSignature methodSignature = (MethodSignature)point.getSignature();
        Method method = methodSignature.getMethod();
        // 获取注解Action
        cn.itcalvin.sncoal.cth.aspect.NotAuthAnnotation notAuthAnnotation = method.getAnnotation(cn.itcalvin.sncoal.cth.aspect.NotAuthAnnotation.class);

        if(notAuthAnnotation==null){
            String token = request.getHeader("token");
            if(StrUtil.isNotEmpty(token)){
                userInfo = JwtUtil.getUserInfo(token);
                if(userInfo==null){
                    throw new AuthException(ResultStatus.TOKEN_ERROR.getReasonPhrase());
                }
            }else{
                throw new AuthException(ResultStatus.TOKEN_ERROR.getReasonPhrase());
            }
        }
        Object  result = null;
        try {
            result = point.proceed();
        } catch (Throwable e) {
            log.error("接口调用异常",e);
            throw new BusinessException(e.getMessage());
        }
        return result;
    }

    @AfterReturning(value = "@annotation(logAnnotation)",returning = "result")
    public void  afterReturning(JoinPoint point,LogAnnotation logAnnotation, Object result){
        String strClassName = point.getTarget().getClass().getName();
        String strMethodName = point.getSignature().getName();
        ThreadUtil.execAsync(()->{
            try {
                Long businessId;
                Long userId;
                if(logAnnotation.logType()==1){
                    Message<RespUserInfo> message =   (Message<RespUserInfo>)result;
                    if(message.getCode()==0){
                        logOpService.addLog(logAnnotation.logType(),null,message.getData().getId());
                    }
                }else if(logAnnotation.logType()==2){
                    userId=userInfo.getId();
                    ReqLong reqLong= (ReqLong) point.getArgs()[0];
                    businessId= reqLong.getId();
                    logOpService.addLog(logAnnotation.logType(),businessId,userId);
                }
            }catch (Exception e){
                log.error("日志记录失败",e);
            }
        });
        final String join = StrUtil.join("|", strClassName, strMethodName);
        log.info("{}--请求入参:{}",join,JSONUtil.toJsonStr(point.getArgs()));
        log.info("{}--返回结果:{}",join, JSONUtil.toJsonStr(result));
    }
}
